how to create a static site with python

  1. first up, I strongly recommend you try pelican.

  2. prepare directory structure

    mkdir content output templates
    
  3. prepare templates

    cd templates

    cat index.html

    {% extends "layout.html" %}
    
    {% block content %}
    
    <h1>Site</h1>
    
    <div>
    
    {% for post in posts %}
    
        <p>
            <h2>{{loop.index}}: <a href="posts/{{ post.title }}.html">{{post.title}}</a> </h2>
            <!--{{post.summary}}-->
        </p>
    
    {% endfor %}
    
    </div>
    
    {% endblock %}
    

    cat post.html

    {% extends "layout.html" %}
    
    {% block content %}
    
    <h1>{{post.title}}</h1>
    <p>
        {{post.content}}
    </p>
    
    {% endblock %}
    

    cat layout.html

    <!DOCTYPE html>
    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Site</title>
    </head>
    <body class="container">
    
        {% block content %} {% endblock %}
    
    </body>
    </html>
    
  4. prepare code

    cat site.py

    import os
    from jinja2 import Environment, FileSystemLoader
    from markdown2 import markdown
    
    POSTS = {}
    for markdown_post in os.listdir('content'):
        file_path = os.path.join('content', markdown_post)
        with open(file_path, 'r') as file:
            POSTS[markdown_post] = markdown(file.read(), extras=['metadata'])
    POSTS = {
        post: POSTS[post] for post in sorted(POSTS, key=lambda post: POSTS[post].metadata['title'])
    }
    env = Environment(loader=FileSystemLoader('templates'))
    index_template = env.get_template('index.html')
    post_template = env.get_template('post.html')
    posts_metadata = [POSTS[post].metadata for post in POSTS]
    index_html = index_template.render(posts=posts_metadata)
    with open('output/index.html', 'w') as file:
        file.write(index_html)
    os.makedirs('output/posts/', exist_ok=True)
    for post in POSTS:
        post_metadata = POSTS[post].metadata
        post_data = {
            'title': post_metadata['title'],
            'content': POSTS[post]
        }
        post_html = post_template.render(post=post_data)
        post_file_path = 'output/posts/{title}.html'.format(title=post_metadata['title'])
        with open(post_file_path, 'w') as file:
            file.write(post_html)
    
  5. copy to a web server

    python3 site.py
    cp -r output/* /var/www/html/